/* Copyright (c) 2009-2010, Sean A.O. Harney <sharney3@gmail.com> */

//abstract statement list (no exprs in OMF)

#ifndef FUZZER_ASL_H
#define FUZZER_ASL_H

typedef enum {
    STMT_FUZZDATA, STMT_TARGET, STMT_START, STMT_FLAG,
    STMT_SEND, STMT_EXPECT, STMT_FUNCTIONCALL, STMT_PRINT,
    STMT_INCLUDE, STMT_SHELL, STMT_REPEAT, STMT_SLEEP
} STMT_TYPE;

typedef struct st_asl_node *ASL_NODE_P;
/* note: this typedef needs to be above st_stmt_repeat */

struct st_stmt_fuzzdata {
    char *pattern;		//not NULL if pattern, => pattern_maxlen set
    size_t pattern_maxlen;
    char *file;			//not NULL if file
    bool random;		// set to true implies the fuzzdata_random_* below are set
    size_t random_length_lb;
    size_t random_length_ub;
};

struct st_stmt_target {
    bool command;		// set to true implies command_* below are initialized 
    LLIST_P command_argv;	// llist of c strings
    bool command_stdin;
    int command_ind_dollar;	// set to -1 if no "$$' in command_argv, else index into command_argv

    bool dl;			//set to true implies the dl_* below are set to not NULL,etc
    LLIST_P dl_args;		//llist of struct st_dlarg
    char *dl_libfname;
    char *dl_symbol;
    int dl_ind_dollar;		//-1 or index into dl_args for $$

    bool socket;		// set to true implies socket_* below are initialized 
    char *socket_host;
    int socket_port;
    int socket_type;
};


struct st_stmt_start {
    int start_arg;		// -1 for default
};

struct st_stmt_flag {
    bool termination_any;
    bool termination_signal_any;
    bool termination_exit_any;
    bool termination_signal;	// => val is set
    bool termination_exit;	// => val is set
    int val;
};

struct st_stmt_send {
    uint8_t *buf;
    size_t len;
};

struct st_stmt_expect {
    int tmp;
};

struct st_stmt_functioncall {
    char *symname;
};

struct st_stmt_print {
    char *msg;
};

struct st_stmt_include {
    char *file;
};

struct st_stmt_shell {
    char *command_str;
};

struct st_stmt_repeat {
    int n; // number of times to loop. < 0 for infinite loop.
    ASL_NODE_P stmt; // ptr to stmt to loop. Technically ASL(ist) is a tree now perhaps.
    // only interested in single stmt //TODO: ASL_NODE_P *block //unnamed ASL block 
};

struct st_stmt_sleep {
    int secs;
};

struct st_asl_node {
    STMT_TYPE type;
    int lineno;
    char *filename;
    union {
	struct st_stmt_fuzzdata stmt_fuzzdata;
	struct st_stmt_target stmt_target;
	struct st_stmt_start stmt_start;
	struct st_stmt_flag stmt_flag;
	struct st_stmt_send stmt_send;
	struct st_stmt_expect stmt_expect;
	struct st_stmt_functioncall stmt_functioncall;
	struct st_stmt_print stmt_print;
	struct st_stmt_include stmt_include;
	struct st_stmt_shell stmt_shell;
	struct st_stmt_repeat stmt_repeat;
	struct st_stmt_sleep stmt_sleep;
    } params;			// stmt params
};

struct st_asl_cell {
    LLIST_P asl;
    char *symname;
    char *filename;
};


/* prototypes */
LLIST_P asl_prepend(LLIST_P asl, ASL_NODE_P stmt);
LLIST_P asl_append(LLIST_P asl, ASL_NODE_P stmt);
bool asl_add_new_asl(char *symname, LLIST_P asl, char *filename);
LLIST_P asl_get_asl(char *symname);
struct st_asl_cell *asl_get_asl_cell(char *symname);
void asl_print(FILE * fp, LLIST_P asl);
void asl_print_all(FILE * fp);

void omf_state_reset(void);


#endif				/* FUZZER_ASL_H */
